//!
/**
 ***********************************************************************************************************
 * <RelaxUVs implementation>
 ***********************************************************************************************************
 * @file RelaxUVs.cpp
 ***********************************************************************************************************/

/************************************************************************************************************
 * Includes
 ************************************************************************************************************/
#include "RelaxUVs.h"

/************************************************************************************************************/

namespace UVRelaxer
{

void RelaxUVs(const VertexTerrain* input, VertexTerrain* output, uint16 vertexCount, VertexTerrainNeighbor* neighborData)
{
	float2 idealUVs[8];
	uint16 last = vertexCount-1;
	for (uint16 y=0; y < vertexCount; ++y)
	{
		for (uint16 x=0; x < vertexCount; ++x)
		{
			uint16 ui=x+vertexCount*y;
			float2 uvs(0,0);
			if (x==0 ||
				x==last ||
				y==last ||
				y==0)
			{
				float2 pos = float2(input[ui].Pos.x, input[ui].Pos.y);
				for (uint16 neighbor=0; neighbor<neighborData[ui].NeighborCount; ++neighbor)
				{
					uint16 neighborIdx = neighborData[ui].Neighbors[neighbor];
					float3 diff3D = input[ui].Pos - input[neighborIdx].Pos;
					float2 diffSpace = pos - float2(input[neighborIdx].Pos.x, input[neighborIdx].Pos.y);
					diffSpace = diffSpace * (1.0f / diffSpace.GetLength());
					uvs += input[neighborIdx].UVs + g_uvMultiplier * diffSpace * diff3D.GetLength();
				}
				uvs = uvs * (1.0f / neighborData[ui].NeighborCount);
			}
			else
			{
				for (uint16 neighbor=0; neighbor<neighborData[ui].NeighborCount; ++neighbor)
				{
					uint16 neighborIdx = neighborData[ui].Neighbors[neighbor];
					uvs += neighborData[ui].Weights[neighbor] * input[neighborIdx].UVs;
				}
			}
			output[ui].UVs = uvs;
		}
	}
}
}
